package cn.agiledata.bank.interest.service;

import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.util.Date;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.log4j.Logger;
import org.hibernate.CallbackException;
import org.hibernate.type.Type;
import org.springframework.dao.DataAccessException;

import cn.agiledata.bank.hibernateBean.AccountBalance;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.context.support.GenericWebApplicationContext;
import  org.springframework.web.context.support.AbstractRefreshableWebApplicationContext;
import org.springframework.web.context.ContextLoaderServlet;

/**
 * 积数相关的操作
 * @author jessik
 * */
public class MutativeInterestServiceImpl implements IMutativeInterestService {
	final static Logger log = Logger.getLogger(MutativeInterestServiceImpl.class);
	
	/**
	 * 主动产生积数，保存入数据库；用于结算前主动计算截至结算时的剩余积数；
	 * 未作数据库保存，减少 
	 * @param accountBalance 子账户的剩余资金对象
	 */
	public final static String setAccumulation_Active = "setAccumulation(Active)";
	public void setAccumulation(AccountBalance accountBalance) {
		if(log.isDebugEnabled())if(accountBalance==null){
			log.debug(setAccumulation_Active+"accountBalance==null数据不完整。");
			throw new RuntimeException("accountBalance==null");
		}
		try {
			//记录被处理的子账户id
			log.info(setAccumulation_Active+accountBalance.getId());
			//
			long accumulator = this.getAccumulation(accountBalance);
			
			accountBalance.setAccumulation(new Long(accumulator));
			//更新时间
			accountBalance.setBankrollUpdateTime(new Date());
			
			/*
			SubAccount subAccount = accountBalance.getSubAccount();
			accountDAO.addOrUpdateSubAccount(subAccount);
			*/
			
		} catch (DataAccessException e) {
			// TODO Auto-generated catch block
			log.info(setAccumulation_Active,e);
			throw new RuntimeException(e);
		}
		catch (Exception e) {
			// TODO Auto-generated catch block
			log.info(setAccumulation_Active,e);
			throw new RuntimeException(e);
		}
	}
	
	/**
	 * 被触发产生积数，保存入数据对象accountBalamce；当AccountBalance存储时触发；
	 * 用于拦截器，accountBalamce对象乃是dirty对象，被修改后会被自动保存；
	 * @param accountBalamce dirty对象，被修改后会被自动保存
	 * @param id 其余参数参见org.hibernate.Interceptor#onFlushDirty 
	 * @param newValues
	 * @param oldValues
	 * @param properties
	 * @param types
	 * */
	public final static String setAccumulation_Interceptor = "setAccumulation(Interceptor)";
	public void setAccumulation(AccountBalance accountBalance, Serializable accountBalanceId, Object[] currentValues,
			Object[] previousValues, String[] properties, Type[] types) throws CallbackException{
		if(log.isDebugEnabled())
		try {
			//debug信息，打印AccountBalance对象
			log.debug(BeanUtils.describe(accountBalance));
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			log.debug(setAccumulation_Interceptor,e);
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			log.debug(setAccumulation_Interceptor,e);
		} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			log.debug(setAccumulation_Interceptor,e);
		}
		
		try {
			Date bankrollUpdateTime = null;
			Double previousBalance = null,cuurentBalance = null;
			Long accumulation = null;
			int accumulationId = 0,bankrollUpdateTimeId=0;
			
			for ( int i=0; i < properties.length; i++ ) {
			    if ( "balance".equalsIgnoreCase( properties[i] ) ) {
			    	//获取被修改前账户余额
			    	if(previousValues!=null)//测试中碰到previousValues==null
			    	previousBalance = (Double)previousValues[i];
			    	//获取被修改后账户余额
			    	cuurentBalance = (Double)currentValues[i];
			    }			    
			    else if("accumulation".equalsIgnoreCase( properties[i])){
			    	accumulationId=i;
//			    	//获取被修改前账户累计积数
//			    	accumulation=(Long)currentValues[i];
//			    	//以防没有该字段(如果该字段未被修改(非dirty))
//			    	if(accumulation==null)
//			    		accumulation=accountBalance.getAccumulation();
			    }else if("bankrollUpdateTime".equalsIgnoreCase( properties[i])){
//			    	bankrollUpdateTime=(Date)previousValues[i];
			    	bankrollUpdateTimeId=i;
			    }
			}
//			记录被处理的子账户id
			log.info(setAccumulation_Interceptor+",accountBalanceId="+accountBalanceId+";"+accountBalance.getId());
			
			if(previousBalance==null){
				log.info(setAccumulation_Interceptor+previousValues+"==null");
				return ;
			}
			//对于金额没有变化的不计算积数；比如上面的同名方法
			if(previousBalance.doubleValue()==cuurentBalance.doubleValue()){
				log.info("cuurentBalance no change.");
				return;
			}
			
			//获取积数
			accumulation=accountBalance.getAccumulation();
			//获取更新时间
			bankrollUpdateTime=accountBalance.getBankrollUpdateTime();
			//计算积数
			long newAccumulation = MutativeInterestCore.getAccumulation(previousBalance.floatValue(),bankrollUpdateTime);
			//累计积数
//			accountBalance.setAccumulation(new Long((accumulation==null)?0:accumulation.longValue()+newAccumulation));
			currentValues[accumulationId]=new Long((accumulation==null)?0:accumulation.longValue()+newAccumulation);
			//更新时间
//			accountBalance.setBankrollUpdateTime(new Date());
			currentValues[bankrollUpdateTimeId]=new Date();
			
		} catch (RuntimeException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			log.info(setAccumulation_Interceptor,e);
		}
	}
	public final static String getAccumulation_Active = "getAccumulation(Active)";
	/**
	 * @param accountBalance 子账户金额对象
	 * @return 累计积数
	 * */
	public long getAccumulation(AccountBalance accountBalance) throws Exception, RuntimeException {
		// TODO Auto-generated method stub
		if(log.isDebugEnabled())if(accountBalance==null){
			log.debug(getAccumulation_Active+"accountBalance==null数据不完整。");
			throw new RuntimeException("accountBalance==null");
		}
		try {
			//记录被处理的子账户id
			log.info(getAccumulation_Active+accountBalance.getId());
			//获取账户余额
			Double balance = accountBalance.getBalance();
			//获取该余额的生成时间，即最后更新时间(该字段为金额变化专用)
			Date bankrollUpdateTime = accountBalance.getBankrollUpdateTime();
			//计算积数
			long newAccumulation = MutativeInterestCore.getAccumulation(balance.floatValue(),bankrollUpdateTime);
			//累加积数
			return (accountBalance.getAccumulation().longValue()+newAccumulation);
		} catch (DataAccessException e) {
			// TODO Auto-generated catch block
			log.info(getAccumulation_Active,e);
			throw new RuntimeException(e);
		}
		catch (Exception e) {
			// TODO Auto-generated catch block
			log.info(getAccumulation_Active,e);
			throw new RuntimeException(e);
		}
	}
}
 
